import { join, Path, strings } from '@angular-devkit/core';
import {
  apply,
  mergeWith,
  branchAndMerge,
  move,
  Rule,
  chain,
  Source,
  template,
  url,
  Tree,
} from '@angular-devkit/schematics';
import {
  DEFAULT_AUTHOR,
  DEFAULT_DESCRIPTION,
  DEFAULT_LANGUAGE,
  DEFAULT_VERSION,
  DEFAULT_CPAAS_VERSION,
  DEFAULT_CPAAS_FRONT_VERSION,
  DEFAULT_DEMO_NAME,
} from '../defaults';
import { ApplicationOptions } from './cpaas-front-parent.schema';
import { removeTemplateExt } from '../../utils/source-root.helpers';

export function main(options: ApplicationOptions): Rule {
  options = transform(options);
  return mergeWith(generate(options));
}

function transform(options: ApplicationOptions): ApplicationOptions {
  const target: ApplicationOptions = Object.assign({}, options);

  target.author = !!target.author ? target.author : DEFAULT_AUTHOR;
  target.description = !!target.description
    ? target.description
    : DEFAULT_DESCRIPTION;
  target.language = !!target.language ? target.language : DEFAULT_LANGUAGE;
  target.name = strings.dasherize(target.name);
  target.version = !!target.version ? target.version : DEFAULT_VERSION;
  target.cpaasVersion = !!target.cpaasVersion
    ? target.cpaasVersion
    : DEFAULT_CPAAS_VERSION;
  const setObj = {};
  if (target.set) {
    if (typeof target.set === 'string') {
      target.set.split(',').forEach((kv) => {
        const [envName, envValue] = kv.split('=');
        if (envName && envValue) {
          setObj[envName] = envValue;
        }
      });
    }
  }
  target.set = setObj;
  target.demoName = !!target.demoName ? target.demoName : DEFAULT_DEMO_NAME;
  target.cpaasPackages = !!target.cpaasPackages ? target.cpaasPackages : '';
  target.cpaasFrontVersion = !!target.cpaasFrontVersion
    ? target.cpaasFrontVersion
    : DEFAULT_CPAAS_FRONT_VERSION;
  target.cpaasCliVersion = !!target.cpaasCliVersion
    ? target.cpaasCliVersion
    : require('cpaas-cli/package.json').version;

  target.packageManager = !!target.packageManager
    ? target.packageManager
    : 'npm';
  target.dependencies = !!target.dependencies ? target.dependencies : '';
  target.devDependencies = !!target.devDependencies
    ? target.devDependencies
    : '';
  return target;
}

export function addNpmrcRegistry(registry: string): Rule {
  return (host: Tree) => {
    let file = './.npmrc.template';
    if (host.exists(file)) {
      let content = host.read(file).toString() || '';

      if (!content.includes('registry=')) {
        content =
          `registry=${
            registry ||
            'http://nexus.coraise.cn:8000/repository/group/'
          }\n` + content;
        host.overwrite(file, content);
      }
    }
    return host;
  };
}

function generate(options: ApplicationOptions): Source {
  return apply(url(join('./files' as Path, options.language)), [
    template({
      ...strings,
      ...options,
    }),
    addNpmrcRegistry(options.registry),
    move(options.name),
    removeTemplateExt(),
  ]);
}
